//////////////////////////////////////////////////////////////////////////////////
//	Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include "graphctrl.h"

#define GRID_GAP	12
#define MAX_VALS	GRAPH_CTRL_WIDTH

CGraphCtrl::CGraphCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size):
	wxPanel(parent, id, pos, size, wxTAB_TRAVERSAL|wxBORDER_SUNKEN),
	m_btLevel(0), m_nMaxVal(0), m_timer(this)
			
{
	Connect(wxEVT_PAINT, wxPaintEventHandler(CGraphCtrl::OnPaint));
	Connect(wxEVT_SIZE, wxSizeEventHandler(CGraphCtrl::OnSize));
	Connect(wxEVT_TIMER, wxTimerEventHandler(CGraphCtrl::OnTimer));
	
	SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}

CGraphCtrl::~CGraphCtrl()
{
	if ( m_timer.IsRunning() )
		m_timer.Stop();
}

void CGraphCtrl::SetVal(unsigned int nVal)
{
	SetLevel( (100*nVal)/(m_nMaxVal?m_nMaxVal:1) );
}

void CGraphCtrl::SetLevel(unsigned char perc)
{
	m_btLevel = perc>100?100:perc;
	//fprintf(stderr, "val: %d\n", m_btLevel);
	
	if ( !m_timer.IsRunning() )
		m_timer.Start(TICK_TIME);
}

void CGraphCtrl::OnTimer(wxTimerEvent& event)
{
	wxSize szMe = GetClientSize();
	
	if ( m_vals.size()>(size_t)szMe.GetX() )
		m_vals.pop_front();
		
	m_vals.push_back( m_btLevel );
		
	Refresh();	
}

void CGraphCtrl::OnSize(wxSizeEvent& event)
{
	Refresh();
}

void CGraphCtrl::OnPaint(wxPaintEvent& event)
{
	wxSize szMe = GetClientSize();
	wxBufferedPaintDC dc(this);

	try
	{
		//Clear
		dc.SetBackground(*wxBLACK_BRUSH);
		dc.Clear();
		
		DrawGrid(dc);
		
		DrawGraph(dc);
	}
	catch(...)
	{
	}
}

void CGraphCtrl::DrawGrid(class wxBufferedPaintDC& dc)
{
	wxSize szMe = GetClientSize();
	wxColour 	green(0,128,0);
	wxPen		pen(green);
	dc.SetPen(pen);
	
	for (int i=0;i<szMe.GetX();i+=GRID_GAP)
	{
		dc.DrawLine(i, 0, i, szMe.GetY() );
	}
	
	for (int j=0;j<szMe.GetY();j+=GRID_GAP)
	{
		dc.DrawLine(0, j, szMe.GetX(),j );
	}
}

void CGraphCtrl::DrawGraph(class wxBufferedPaintDC& dc)
{
	if ( !m_vals.empty() )
	{
		GRAPHVALS::iterator iCur;
		wxSize szMe = GetClientSize();
		wxColour 	green(0,255,0);
		wxPen		pen(green);
		double		dblPixPer = (double)szMe.GetY()/100.0;
		int nStart = szMe.GetX()-m_vals.size();
		
		nStart = nStart<0?0:nStart;
		
		dc.SetPen(pen);
		
		wxPoint* points = new wxPoint[m_vals.size()];

		if ( points )
		{
			int i=0;
			
			for (iCur=m_vals.begin();iCur!=m_vals.end();iCur++,i++)
			{
				unsigned char val = *iCur;
				double y  = dblPixPer*(double)(100-val);
				
				points[i].x = nStart+i;
				points[i].y = (int)y;
			}
			
			//dc.DrawLines(m_vals.size(), points );

			if ( m_vals.size()>2 )
			{
				dc.DrawSpline( m_vals.size(), points  );
			}
			
			delete[] points;
		}
	}
}
